package com.ca.singlesignon.config;

import com.ca.singlesignon.utils.RedisShardedPoolUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import org.redisson.api.RLock;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class CloseOrderTask
{

    @Autowired
    private RedissonManager redissonManager;
    @Autowired
    private RedisShardedPoolUtil redisShardedPoolUtil;

    //关闭Tomcat的时候会被调用,强制关锁，但是在杀掉tomcat进程的时候还是不会执行这个方法
    @PreDestroy
    public void delLock(){
        redisShardedPoolUtil.del("CLOSE_ORDER_TASK_LOCK");
    }

    //@Scheduled(cron="0 */1 * * * ?")
    public void closeOrderTask(){
        log.info("关闭订单定时任务开始");
       /* int hour = Integer.parseInt(PropertiesUtil.getProperty("close.order.task.time.hour","2"));
        iOrderService.closeOrder(hour);*/
        log.info("关闭订单定时任务结束");
}

    //@Scheduled(cron="0 */1 * * * ?")
    public void closeOrderTask2(){
        log.info("关闭订单定时任务开始");
        Long lockTimeout = Long.parseLong("5000");
        Long setnx = redisShardedPoolUtil.setnx("CLOSE_ORDER_TASK_LOCK", String.valueOf(System.currentTimeMillis() + lockTimeout));
        if(setnx !=null && setnx.intValue()==1){
            //设置成功，获取锁
            closeOrder("CLOSE_ORDER_TASK_LOCK");
        }else{
            log.info("没有获得分布式锁");
        }

        log.info("关闭订单定时任务结束");
    }

    /**
     * 设置分布式锁
     * 如果获取分布式锁成功就执行关单
     * 如果未获取到分布式锁就再判断过期时间
     * 过期了，就说明有机会获取锁，但是在多进程下，其他进程也会去重置锁
     * 这里就判断lockValueStr   getSetStr 是否相等，判断是否能获取资源
     */
    @Scheduled(cron="0 */1 * * * ?")
    public void closeOrderTask3(){
        log.info("关闭订单定时任务开始");
        Long lockTimeout = Long.parseLong("5000");
        Long setnx = redisShardedPoolUtil.setnx("TASK_LOCK", String.valueOf(System.currentTimeMillis() + lockTimeout));
        if(setnx !=null && setnx.intValue()==1){
            //设置成功，获取锁
            closeOrder("TASK_LOCK");
        }else{
            log.info("没有获得分布式锁,继续判断时间戳,是否可以重置并获取到锁");
            String lockValueStr = redisShardedPoolUtil.get("TASK_LOCK");
            if(lockValueStr!=null && System.currentTimeMillis()>Long.parseLong(lockValueStr)){
                //锁过期后，其他进程有权利获取到锁
                String getSetStr = redisShardedPoolUtil.getSet("TASK_LOCK", String.valueOf(System.currentTimeMillis() + lockTimeout));
                //判断是否被其它线程获取值
                if (getSetStr == null || ( getSetStr!=null && StringUtils.equals(lockValueStr,getSetStr) ) ) {
                    //获取到锁
                    closeOrder("TASK_LOCK");
                }else{
                    log.info("没有获取到分布式锁：{}","TASK_LOCK");
                }
            }else{
                log.info("没有获取到分布式锁：{}","TASK_LOCK");
            }
        }
        log.info("关闭订单定时任务结束");
    }
    /*线上采用redisson解决分布式锁实现定时关单业务*/
    //@Scheduled(cron="0 */1 * * * ?")
    public void closeOrderTask4(){
        RLock lock=redissonManager.getRedisson().getLock("TASK_LOCK");
        boolean getLock=false;
        try {
            //// 尝试加锁，最多等待0秒，上锁以后5秒自动解锁
            if(getLock=lock.tryLock(0, 5, TimeUnit.SECONDS)){
                log.info("Redisson获取分布式锁:{},ThreadName:{}","TASK_LOCK",Thread.currentThread());
                int hour = Integer.parseInt("1");
            }else{
                log.info("Redisson未获取分布式锁:{},ThreadName:{}","TASK_LOCK",Thread.currentThread());
            }
        } catch (InterruptedException e) {
            log.error("Redisson分布式锁获取异常:{}",e);
        }finally {
            log.info("Redisson分布式锁 释放资源");
            if(!getLock){
                return;
            }
            lock.unlock();
            //打印日志
            log.info("Redisson 分布式释放锁");
        }
    }

    private void closeOrder(String lockName){
        redisShardedPoolUtil.expire(lockName,5);//有效期五秒
        log.info("获取{},ThreadName:{}","CLOSE_ORDER_TASK_LOCK",Thread.currentThread());
        int hour = Integer.parseInt("1");
        redisShardedPoolUtil.del("TASK_LOCK");
    }
}
